#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024/5/14 16:32
# @Author  : liutianwei
# @File    : FormatRateInfo.py
# @Software: PyCharm
import math
import os


class formatRateInfo:
    def __init__(self, tmpRecPra, tmpRecSys, recTxtDict, output, tmpRef, tmpRec, tmpRecRaw, confidLevel, oldrefTxt, old_recTxt):
        self.pra = tmpRecPra
        self.sys = tmpRecSys
        self.raw = tmpRecRaw
        self.tmpRef = tmpRef
        self.tmpRec = tmpRec
        self.recDict = recTxtDict
        self.output = open(output, "w")
        self.confidLevel = confidLevel
        self.oldrefTxt = oldrefTxt
        self.old_recTxt = old_recTxt

        if not os.path.isfile(self.pra):
            print("No cache found! -- [%s]" % self.pra)
        if not os.path.isfile(self.sys):
            print("No cache found! -- [%s]" % self.sys)
        if not os.path.isfile(self.tmpRef):
            print("No cache found! -- [%s]" % self.tmpRef)
        if not os.path.isfile(self.tmpRec):
            print("No cache found! -- [%s]" % self.tmpRec)
        if not os.path.isfile(self.raw):
            print("No cache found! -- [%s]" % self.raw)
        if self.recDict == None:
            print("Rec dict exception!")
        if len(self.recDict.keys()) == 0:
            print("Rec dict is empty!")

    def handlePraBlock(self, tmpAry):
        IDTag = "id: ("
        SOTag = "Scores: ("
        RFTag = ["REF:", ">> REF:"]
        RCTag = ["HYP:", ">> HYP:"]
        Eid = ""
        """right: [0:right, 1:wrong, 2:null]"""
        formatAry = {"score": "", "ref": "", "rec": "", "right": 0}
        for sent in tmpAry:
            sent = sent.strip()
            if sent.startswith(IDTag):
                Eid = sent[sent.find(IDTag) + len(IDTag): len(sent) - 1].strip()
            elif sent.startswith(SOTag):
                formatAry["score"] = sent[sent.find(")") + 1:].strip()
                if sent[sent.find(")") + 1:].strip().endswith(" 0 0 0"):
                    formatAry["right"] = 0
                elif sent[sent.find(")") + 1:].strip().startswith("0 0 ") and sent[
                                                                              sent.find(")") + 1:].strip().endswith(
                        " 0"):
                    formatAry["right"] = 2
                else:
                    formatAry["right"] = 1
            elif sent.startswith(RFTag[0]):
                # formatAry["ref"] = formatAry.get("ref") + sent[sent.find(RFTag[0])+len(RFTag[0]) : ].strip().replace(" ","")
                formatAry["ref"] = formatAry.get("ref") + " " + sent[sent.find(RFTag[0]) + len(RFTag[0]):].strip()
            elif sent.startswith(RFTag[1]):
                # formatAry["ref"] = formatAry.get("ref") + sent[sent.find(RFTag[1])+len(RFTag[1]) : ].strip().replace(" ","")
                formatAry["ref"] = formatAry.get("ref") + " " + sent[sent.find(RFTag[1]) + len(RFTag[1]):].strip()
            elif sent.startswith(RCTag[0]):
                # formatAry["rec"] = formatAry.get("rec") + sent[sent.find(RCTag[0])+len(RCTag[0]) : ].strip().replace(" ","")
                formatAry["rec"] = formatAry.get("rec") + " " + sent[sent.find(RCTag[0]) + len(RCTag[0]):].strip()
            elif sent.startswith(RCTag[1]):
                # formatAry["rec"] = formatAry.get("rec") + sent[sent.find(RCTag[1])+len(RCTag[1]) : ].strip().replace(" ","")
                formatAry["rec"] = formatAry.get("rec") + " " + sent[sent.find(RCTag[1]) + len(RCTag[1]):].strip()
        return Eid, formatAry

    """ read pra and formatted output,such as ( dict[id] = {"score":"", "ref":"", "rec":""} )"""

    def readPra(self):
        pradata = open(self.pra, encoding="utf-8")
        tmpAry = []
        praDict = {}
        for line in pradata:
            line = line.strip()
            if len(line) <= 0 or line == "": continue
            if line.startswith(">> Eval:") or line.startswith("Eval:"): continue
            if line.startswith("id: ("):
                id, blockDict = self.handlePraBlock(tmpAry)
                if id.strip() != "" and len(id.strip()) > 0:
                    praDict[id] = blockDict
                tmpAry = []
            tmpAry.append(line)
        if len(tmpAry) > 0:
            id, blockDict = self.handlePraBlock(tmpAry)
            if id.strip() != "" and len(id.strip()) > 0:
                praDict[id] = blockDict
            tmpAry = []
        pradata.close()
        return praDict

    """read sys and formatted output."""

    def readSys(self):
        sysdata = open(self.sys)
        title = ""
        countinfo = ""
        for line in sysdata:
            if line.strip().find("Sum/Avg") > -1:
                countinfo = line.strip()
            elif line.strip().find("SPKR") > -1 and line.strip().find("Corr") > -1:
                title = line.strip()
        sysdata.close()
        return title, countinfo

    """ read pra and formatted output,such as ( dict[id] = {"score":"", "ref":"", "rec":"","right":,"confidence","
    ","rectimecost": "","audtimelen":"","realtime":""} )"""

    def updatePraDict(self):
        praDict = self.readPra()

        """formatted output type, such as( dict[id] = [val, confidence,rec time cost,audio time,read time])"""
        for key in self.recDict.keys():
            if praDict.__contains__(key):
                valAry = self.recDict.get(key)
                if len(valAry) >= 5:
                    praDict.get(key)["confidence"] = valAry[1]
                    praDict.get(key)["recTcost"] = valAry[2]
                    praDict.get(key)["audTleng"] = valAry[3]
                    praDict.get(key)["realTime"] = valAry[4]
                else:
                    print("rate exception line -- [%s]" % key)
            else:
                print("rate exception line -- [%s]" % key)
        return praDict

    def sumInfo(self, newPraDict):
        """return rightDict,wrongDict,nullDict,sum info str"""
        """rate sum info: 21(Total)   0--0.0%(Right)  21--100.0%(Wrong)   0--0.0%(Null)"""
        if newPraDict == None or len(newPraDict.keys()) <= 0:
            print("Rate pra dict exception!", "LOG_ERRO")
        rightDict = {}
        wrongDict = {}
        nullDict = {}
        sumTotal = len(newPraDict.keys())
        sumRight = 0
        sumWrong = 0
        sumNull = 0
        for Eid in newPraDict.keys():
            infoDict = newPraDict.get(Eid)
            if infoDict.get("right") == 0:
                rightDict[Eid] = infoDict
                sumRight += 1
            elif infoDict.get("right") == 1:
                wrongDict[Eid] = infoDict
                sumWrong += 1
            elif infoDict.get("right") == 2:
                nullDict[Eid] = infoDict
                sumNull += 1
        sumInfo = "Rec number:\n%d(Total)    %d--%s%s(Right)" % (
        sumTotal, sumRight, str(round(float(sumRight) * 100 / sumTotal, 2)), "%")
        sumInfo += "    %d--%s%s(Wrong)" % (sumWrong, str(round(100.0 * sumWrong / sumTotal, 2)), "%")
        sumInfo += "    %d--%s%s(Null)\n" % (sumNull, str(round(100.0 * sumNull / sumTotal, 2)), "%")
        # print sumInfo
        return rightDict, wrongDict, nullDict, sumInfo

    def timeInfo(self, newPraDict):
        if newPraDict == None or len(newPraDict.keys()) <= 0:
            print("Rate pra dict exception!", "LOG_ERRO")
        rtMax = -2147483648
        rtMin = 2147483647
        totalRECTime = 0.0
        totalAudTime = 0.0

        rcMax = -2147483648
        rcMin = 2147483647

        for Eid in newPraDict.keys():
            infoDict = newPraDict.get(Eid)
            totalRECTime += infoDict.get("recTcost")
            totalAudTime += infoDict.get("audTleng")
            if infoDict.get("realTime") > rtMax:
                rtMax = infoDict.get("realTime")
            if infoDict.get("realTime") < rtMin:
                rtMin = infoDict.get("realTime")

            if infoDict.get("recTcost") > rcMax:
                rcMax = infoDict.get("recTcost")
            if infoDict.get("recTcost") < rcMin:
                rcMin = infoDict.get("recTcost")

        if totalAudTime <= 0.0:
            rtAvg = round(0, 6)
            rcAvg = round(0, 6)
        else:
            rtAvg = round(totalRECTime / totalAudTime, 6)
            rcAvg = round(totalRECTime / len(newPraDict.keys()), 6)

        TDAvgX = 0.0
        for Eid in newPraDict.keys():
            infoDict = newPraDict.get(Eid)
            TDAvgX += math.pow(infoDict.get("realTime") - rtAvg, 2)

        DAvgX = round(TDAvgX / len(newPraDict.keys()), 6)
        realtimeinfo = "Real time(s):\n%f(Avg)    %f(Max)    %f(Min)    %f(D_AVGX)\n" % (rtAvg, rtMax, rtMin, DAvgX)
        recotimeinfo = "Reco time(ms):\n%f(AVG)    %f(Max)    %f(Min)\n" % (rcAvg, rcMax, rcMin)
        return realtimeinfo, recotimeinfo

    def confidenceInfo(self, newPraDict):
        if newPraDict == None or len(newPraDict.keys()) <= 0:
            print("Rate pra dict exception!")
        confidDict = {}
        score = 100
        confidLevel = self.confidLevel if not self.confidLevel == None else 10
        level = int(score / confidLevel) + 1;
        tmpList = []
        for num in range(0, level):
            start = score - (num + 1) * confidLevel
            end = score - num * confidLevel
            if start < 0: start = 0
            if start < end:
                confidDict["%d--%d" % (start, end)] = 0
                tmpList.append("%d--%d" % (start, end))

        for Eid in newPraDict.keys():
            infoDict = newPraDict.get(Eid)
            confidence = infoDict.get("confidence")
            for key in confidDict.keys():
                scoArr = key.strip().split("--")
                if len(scoArr) == 2:
                    start = int(scoArr[0])
                    end = int(scoArr[1])
                    if start == 0:
                        if confidence >= start and confidence <= end: confidDict[key] += 1;break
                    else:
                        if confidence > start and confidence <= end: confidDict[key] += 1;break
        confidInfo = "Confidence:\n"
        for key in tmpList:
            if (confidDict.__contains__(key)):
                if confidDict.get(key) == 0: continue
                confidInfo += "(%s]\t%d\t%d\t" % (key, confidDict.get(key), len(newPraDict.keys()))
                confidInfo += "%s%s\n" % (str(round(float(confidDict.get(key) * 100) / len(newPraDict.keys()), 2)), "%")
            else:
                print("confidence info exception!", "LOG_WAIN")
        return confidInfo

    def getRateInfo(self, newPraDict):
        """rate sum info     : 21(Total)   0--0.0%(Right)  21--100.0%(Wrong)   0--0.0%(Null)"""
        """rate real time(s) : 0.609455(Avg)   0.69(Max)   0.48(Min)   0.002566(D_AVGX)"""
        """rate reco time(ms): 229761.92(Avg)  299000.28(Max)  166999.5(Min)"""
        """rate confidence   : (90--100]   15  21  71.4286% ..."""
        """return rightDict,wrongDict,nullDict,countList[sum info str, real time str, reco time str, confidence info str]"""
        rightDict, wrongDict, nullDict, sumInfo = self.sumInfo(newPraDict)
        rtInfo, rcInfo = self.timeInfo(newPraDict)
        cfdInfo = self.confidenceInfo(newPraDict)

        return rightDict, wrongDict, nullDict, sumInfo, rtInfo, rcInfo, cfdInfo;

    """ format head info and write"""

    def writeHead(self):
        title, countinfo = self.readSys()
        linex = ""
        length = len(title) - 2 if len(title) > 2 else len(title)
        for index in range(0, length):
            linex += "-"
        title = title.replace("SPKR", "PASR").replace("#", " ")
        rateinfo = " %s\n%s\n %s\n%s\n %s\n\n" % (linex, title, linex, countinfo, linex)
        self.output.write(rateinfo)
        print
        " %s" % rateinfo.strip()
        return countinfo

    """ format body info and write"""

    def writeBody(self, newPraDict):
        rightDict, wrongDict, nullDict, sumInfo, rtInfo, rcInfo, cfdInfo = self.getRateInfo(newPraDict)
        self.output.write("%s\n" % sumInfo)
        self.output.write("%s\n" % rtInfo)
        self.output.write("%s\n" % rcInfo)
        self.output.write("%s\n" % cfdInfo)
        """ read pra and formatted output,such as ( dict[id] = {"score":"", "ref":"", "rec":"","right":,"confidence","
        ","rectimecost": "","audtimelen":"","realtime":""} )"""
        if rightDict != None and len(rightDict.keys()) > 0:
            self.output.write("\nR-------------------------------------------------------\n")
            for key in rightDict.keys():
                infoDict = rightDict.get(key)
                tmpstr = "AID: %s\n" % (key)
                tmpstr += "REF: %s\n" % (self.oldrefTxt.get(key))
                tmpstr += "HYF: %s\n" % (self.old_recTxt.get(key))
                tmpstr += "INF: %s %d %d %f " % (
                infoDict.get("score"), 0, infoDict.get("confidence"), infoDict.get("recTcost"))
                tmpstr += "%f %f\n\n" % (infoDict.get("audTleng"), infoDict.get("realTime"))
                self.output.write(tmpstr)
        if wrongDict != None and len(wrongDict.keys()) > 0:
            self.output.write("\nW-------------------------------------------------------\n")
            for key in wrongDict.keys():
                infoDict = wrongDict.get(key)
                tmpstr = "AID: %s\n" % (key)
                tmpstr += "REF: %s\n" % (self.oldrefTxt.get(key))
                tmpstr += "HYF: %s\n" % (self.old_recTxt.get(key))
                tmpstr += "INF: %s %d %d %f " % (
                infoDict.get("score"), 100, infoDict.get("confidence"), infoDict.get("recTcost"))
                tmpstr += "%f %f\n\n" % (infoDict.get("audTleng"), infoDict.get("realTime"))
                self.output.write(tmpstr)
        if nullDict != None and len(nullDict.keys()) > 0:
            self.output.write("\nN-------------------------------------------------------\n")
            for key in nullDict.keys():
                infoDict = nullDict.get(key)
                tmpstr = "AID: %s\n" % (key)
                tmpstr += "REF: %s\n" % (self.oldrefTxt.get(key))
                tmpstr += "HYF: %s\n" % (self.old_recTxt.get(key))
                tmpstr += "INF: %s %d %d %f " % (
                infoDict.get("score"), 100, infoDict.get("confidence"), infoDict.get("recTcost"))
                tmpstr += "%f %f\n\n" % (infoDict.get("audTleng"), infoDict.get("realTime"))
                self.output.write(tmpstr)

        return sumInfo

    """ format foot info and write"""

    def writeFoot(self):
        footinfo = "\n\n"
        footinfo += "========================================================\n"
        footinfo += "Example:\n"
        footinfo += "AID /var/samba/home/cutwav4ht/wave/03916/3916494.wav\n"
        footinfo += "REF 你在干什么呢你在干什么呢\n"
        footinfo += "HYF 你在干什么呢你在干什么\n"
        footinfo += "INF 11  10  1  0  100  99   2978.0  3521.0  0.845782\n"
        footinfo += "SIG C   S   D  I  SER  WEI  RCT     AT      RT\n"
        footinfo += "EXP C:字正确数 S:字替换错误数 D:字删除错误数\n"
        footinfo += "EXP I:字插入错误数 SER:句子错误率 WEI:置信度\n"
        footinfo += "EXP RCT:识别时长 AT:音频时长 RT:实时时间\n"
        footinfo += "========================================================\n"
        self.output.write(footinfo)
        return 1

    def clean(self):
        if os.path.isfile(self.pra) and os.path.isfile(self.sys) and os.path.isfile(self.raw):
            os.remove(self.pra)
            os.remove(self.sys)
            os.remove(self.raw)
            print
            ""
        else:
            print("No cache found! -- [%s-%s-%s]" % (self.pra, self.sys, self.raw), "LOG_WAIN")
        if os.path.isfile(self.tmpRef) and os.path.isfile(self.tmpRec):
            os.remove(self.tmpRef)
            os.remove(self.tmpRec)
        else:
            print("No cache found! -- [%s-%s]" % (self.tmpRef, self.tmpRec), "LOG_WAIN")
        return 1

    def format(self):
        print("Write rate info!")
        header_info = self.writeHead()
        sumInfo = self.writeBody(self.updatePraDict())
        self.writeFoot()
        self.clean()
        return sumInfo
